﻿// Gecko = Netscape 7.x & Mozilla 1.4+
var tmpText = "";
LastNo = 0;
SPACECHAR = " "; // 空白字元。
CandChinesePart = new Array(); //侯选字，中文字部份
CandCompPart = new Array();    //侯选字, 后码部份，如“我o”里的o
AsciiStr = "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z"; //定义使用的编码。
AsciiStr = AsciiStr.split(',');
ArabicNumbers = "0,1,2,3,4,5,6,7,8,9";
ArabicNumbers = ArabicNumbers.split(',');
var CodeList = CodeListNew;
CodeList = CodeList.split(',');

CtrlDown = false;
CancelKey = false;

deleteChar = false;
//==KeyCode 33..47
//Symbol1 = "！＂＃＄％＆＇（）＊＋，－。／";
//==KeyCode 58..64
//Symbol2 = "：；＜＝＞？＠";
//==KeyCode 91..96
//Symbol3 = "［、｝＾＿｀";
//==KeyCode 123..126
//Symbol4 = "｛｜］～";

Punct2 = new Array('；', '＝', '，', '－', '。', '／', '｀');
Punct3 = new Array('［', '、', '］', '＇');

//==按ＳＨＩＦＴ输出的符号
SPunct1 = new Array('）', '！', '＠', '＃', '＄', '％', '＾', '＆', '＊', '（');
SPunct2 = new Array('：', '＋', '＜', '＿', '＞', '？', '～');
SPunct3 = new Array('｛', '｜', '｝', '＂');

//==全形数字和字母
FullShape_No = new Array("０", "１", "２", "３", "４", "５", "６", "７", "８", "９");
FullShape_BigAZ = new Array("Ａ", "Ｂ", "Ｃ", "Ｄ", "Ｅ", "Ｆ", "Ｇ", "Ｈ", "Ｉ", "Ｊ", "Ｋ", "Ｌ", "Ｍ", "Ｎ", "Ｏ", "Ｐ", "Ｑ", "Ｒ", "Ｓ", "Ｔ", "Ｕ", "Ｖ", "Ｗ", "Ｘ", "Ｙ", "Ｚ");
FullShape_SmallAZ = new Array('ａ', 'ｂ', 'ｃ', 'ｄ', 'ｅ', 'ｆ', 'ｇ', 'ｈ', 'ｉ', 'ｊ', 'ｋ', 'ｌ', 'ｍ', 'ｎ', 'ｏ', 'ｐ', 'ｑ', 'ｒ', 'ｓ', 'ｔ', 'ｕ', 'ｖ', 'ｗ', 'ｘ', 'ｙ', 'ｚ');

// 二分搜索法
function FindIn(s) {
    var find = -1, low = 0, mid = 0, high = CodeList.length;
    var sEng = "";
    while (low < high) {
        mid = (low + high) / 2;
        mid = Math.floor(mid);
        sEng = CodeList[mid];
        if (sEng.indexOf(s, 0) == 0) { find = mid; break; }
        sEng = CodeList[mid - 1];
        if (sEng.indexOf(s, 0) == 0) { find = mid; break; }
        if (sEng < s) { low = mid + 1; } else { high = mid - 1; }
    }
    while (find > 0) {
        sEng = CodeList[find - 1];
        if (sEng.indexOf(s, 0) == 0) { find--; } else { break; }
    }
    return (find);
}

function GetStr(No, s) {
    var sTmp = "", sChi = "";
    for (i = 0; i <= 9; i++) {
        if (No + i >= CodeList.length - 1) { break; }
        sTmp = CodeList[No + i];
        if (sTmp.indexOf(s) >= 0) {
            sChi = CodeList[No + i];
            CandCompPart[i] = sChi.substring(s.length, sChi.indexOf(SPACECHAR));
            CandChinesePart[i] = sChi.substr(sChi.lastIndexOf(SPACECHAR) + 1);
            if (i <= 8) { IME.Cand.value += (i + 1) + "." + CandChinesePart[i] + CandCompPart[i] + '\n'; }
            else { IME.Cand.value += (0) + "." + CandChinesePart[i] + CandCompPart[i] + '\n'; }
            LastNo = No + i;
        } else { LastNo = -1; }
    }
}

function Grep(s) {
    var No = -1;
    for (i = 0; i <= 9; i++) { CandChinesePart[i] = ""; }
    if (s != "") {
        No = FindIn(s);
        if (No >= 0) { GetStr(No, s); }
    }

    //==自动上字
    if (IME.AutoUp.checked == true && CandChinesePart[0] != "" && CandChinesePart[1] == "" && CandCompPart[0] == "") {
        SendCand(0);
    }
    
    return No;
}

// 送候选字到输入区
function SendCand(n) {
    if (n >= 0 && n <= 9) {
        SendStr(CandChinesePart[n]);
        IME.Comp.value = "";
        IME.Cand.value = "";
    }
}

// 设选区：暂时无用
function setSelectionRange(input, selectionStart, selectionEnd) {
    if (input.setSelectionRange) {
        input.focus();
        input.setSelectionRange(selectionStart, selectionEnd);
    } else if (input.createTextRange) {
        var range = input.createTextRange();
        range.collapse(true);
        range.moveEnd('character', selectionEnd);
        range.moveStart('character', selectionStart);
        range.select();
    }
}
// 设光标位置：暂时无用
function setCaretToEnd(input) {
    setSelectionRange(input, input.value.length, input.value.length);
}
function setCaretToBegin(input) {
    setSelectionRange(input, 0, 0);
}
function setCaretToPos(input, pos) {
    setSelectionRange(input, pos, pos);
}

// 送字串到输入区
function SendStr(s) {
    
    if (s == "") { return }

    switch (browser) {
        case 1: // IE
            var r = document.selection.createRange();
            r.text = s;
            r.select(); // 不知何故，此码可取消选区。
            break;
        case 2: // Gecko
            /*
            -simulate keypress
            *simulate scroll
            -change outputString
            -use createRange, setStart, setEnd
            */

            var obj = IME.InputArea;
            var selectionStart = obj.selectionStart;
            var selectionEnd = obj.selectionEnd;
            var oldScrollTop = obj.scrollTop;  //因Gecko不会滚到该滚的地方。
            var oldScrollHeight = obj.scrollHeight;
            var oldLen = obj.value.length;

            obj.value = obj.value.substring(0, selectionStart) + s + obj.value.substring(selectionEnd); // 这时Gecko会将scrollTop改成0
            obj.selectionStart = obj.selectionEnd = selectionStart + s.length;
            if (obj.value.length == oldLen) { // 如果用户在后面输入，就直接滚到后面。
                obj.scrollTop = obj.scrollHeight;
            } else if (obj.scrollHeight > oldScrollHeight) { // 如果TextArea增加了高度，就滚下一点点
                obj.scrollTop = oldScrollTop + obj.scrollHeight - oldScrollHeight;
            } else { // 其它情形就滚回之前的地方
                obj.scrollTop = oldScrollTop;
            }

            break;
        default: // 其它，就在后面加字算了
            IME.InputArea.value += s;
    }
    IME.InputArea.value += s;
    //tmpText = IME.InputArea.value;
    //alert(tmpText);
}

// 将半形字母换成全形字母
function ToFullShapeLetter(aStr) {
    var s = "";

    for (i = 0; i < aStr.length; i++) {
        var c = aStr.charCodeAt(i);
        if (c >= 65 && c <= 90) {
            s += FullShape_BigAZ[c - 65];
        } else if (c >= 97 && c <= 122) {
            s += FullShape_SmallAZ[c - 97];
        } else {
            s += aStr.charAt(i);
        }
    }

    return s;
}

// 分析控制字符，将结果写到 输入区
function ImeKeyDown(e) {
    var s = "";
    var key = e.which ? e.which : e.keyCode;

    CtrlDown = false;

    switch (key) {
        //==Backspace
        case 8:
            if (IME.Comp.value != "") {
                s = IME.Comp.value;
                IME.Comp.value = s.substr(0, s.length - 1);


                IME.Cand.value = "";
                Grep(IME.Comp.value);
                //TODO: how to cancel KeyDown in Opera 7.11? Hack it?
                CancelKey = true;
                return (false);
            }
            else {
                if (IME.InputArea.value.length > 0) {
                    IME.InputArea.value = IME.InputArea.value.substr(0, IME.InputArea.value.length - 1);
                }
                if (e.element && e.element.value.length > 0) {
                    e.element.value = e.element.value.substr(0, e.element.value.length - 1);
                }
                if (e.element && e.element.value.length == 0) {
                    IME.InputArea.value = "";
                }
                //return (false);
            }
            return (true);

            //==Tab
        case 9:
            SendStr('　');
            CancelKey = true;
            return (false);

            //==Esc
        case 27:
            IME.Comp.value = "";
            IME.Cand.value = "";
            CancelKey = true;
            return (false); //Esc会把全部文字删除，故禁止 Esc键 起任何作用。

            //==PageUp
        case 33:
        case 57383: // Opera 7.11
            s = IME.Comp.value;
            if (s != "") {
                IME.Cand.value = "";
                if ((LastNo - 19) > FindIn(s)) {
                    LastNo = LastNo - 19; GetStr(LastNo, s);
                } else {
                    GetStr(FindIn(s), s);
                }
                CancelKey = true;
                return (false);
            }
            return (true);

            //==PageDown
        case 34:
        case 57384: // Opera 7.11
            s = IME.Comp.value;
            if (s != "" && LastNo != -1) {
                IME.Cand.value = "";
                GetStr(LastNo + 1, s);
                CancelKey = true;
                return (false);
            }
            return (true);

            //==Space
        case 32:
            if (IME.Comp.value != "") {
                //TODO: sound if nothing in Cand
                SendCand(0);
                CancelKey = true;
                return (false);
            }
            return (true);

            //==Enter
        case 13:
            if (IME.Comp.value != "") {
                SendStr(IME.FullShape.checked ?
        ToFullShapeLetter(IME.Comp.value) :
        IME.Comp.value);
                IME.Comp.value = "";
                IME.Cand.value = "";
                CancelKey = true;
                return (false);
            }
            return (true);

            //==F12
        case 123:
        case 57356: // Opera 7.11
            IME.FullShape.checked = !IME.FullShape.checked;
            CancelKey = true;
            return (false);

            //==Ctrl
        case 17:
        case 57402: // Opera 7.11
            CtrlDown = true;
            break;
    }

    if (e.ctrlKey) { return (true) };

    //==数字(0-9)
    if (key >= 48 && key <= 57) {
        if (e.shiftKey) { // 0-9????
            if (IME.FullShape.checked || !IME.EnglishMode.checked) {
                SendStr(SPunct1[key - 48]);
                CancelKey = true;
                return (false);
            }
        }
        else if (IME.arabicNumerals) {
            return true;
        }
        else { // ??
            if (IME.Comp.value == "") {
                if (IME.FullShape.checked || !IME.EnglishMode.checked) {
                    SendStr(FullShape_No[key - 48]);
                    CancelKey = true;
                    return (false);
                }
            } else {
                if (!IME.EnglishMode.checked) {
                    SendCand(key == 48 ? 9 : (key - 49));
                    CancelKey = true;
                    return (false);
                }
            }
        }
        return (true);
    }
    //==其它符号
    if (IME.FullShape.checked || !IME.EnglishMode.checked) {
        if (key >= 186 && key <= 192) { // 制作表格的符号
            SendStr(e.shiftKey ? SPunct2[key - 186] : Punct2[key - 186]);
            CancelKey = true;
            return (false);
        }
        // 处理 “'”
        if (key == 222) return true;
        
        if (key >= 219 && key <= 222) { // 黑方块
            SendStr(e.shiftKey ? SPunct3[key - 219] : Punct3[key - 219]);
            CancelKey = true;
            return (false);
        }
    }

    if (browser == 2) {
        if (IME.FullShape.checked || !IME.EnglishMode.checked) {
            switch (key) {
                case 59: // "Gecko 之分号和冒号" 的 keyCode 是 59
                    SendStr(e.shiftKey ? SPunct2[0] : Punct2[0]);
                    CancelKey = true;
                    return (false);
                case 61:
                    SendStr(e.shiftKey ? SPunct2[1] : Punct2[1]);
                    CancelKey = true;
                    return (false);
                case 109:
                    SendStr(e.shiftKey ? SPunct2[3] : Punct2[3]);
                    CancelKey = true;
                    return (false);
            }
        }
    }

    return (true);
}

function ImeKeyPress(e) {
    var key = e.which ? e.which : e.keyCode;

    // Gecko 虽不能于 OnKeyDown 取消键，但它却是在 OnKeyPress 之后才执行键的动作，故于 OnKeyPress 取消键亦无所谓。
    // 但 Opera 在 OnKeyPress 之前已执行键的动作，故仍未能取消 Backspace 等键。  
    // 为什么不连IE也在此取消多一次？即在OnKeyDown取消，在OnKeyPress再取消。因会出现一个问题：快速输入文字时，第一个字会被取消。原因未知。
    if (browser == 2 || browser == 3) {
        if (CancelKey) {
            CancelKey = false;
            return (false);
        }
    }

    if (e.ctrlKey) { return (true); }

    // 为何不将A-Z的处理放在OnKeyDown ? 因无从知道Caps Lock的状况。
    //==A-Z
    if (key >= 65 && key <= 90) {
        if (IME.FullShape.checked) {
            SendStr(FullShape_BigAZ[key - 65]);
            return (false);
        }
        return (true);
    }

    // == 加了数字
    if (key >= 48 && key <= 57) {
        s = IME.Comp.value;
        if (s.length < MAX) {
            IME.Comp.value += ArabicNumbers[key - 48];
            IME.Cand.value = "";
            Grep(IME.Comp.value);
        }
        return (false);
    }
    

    //==a-z ,加了"'":39
    if (key == 39 || (key >= 97 && key <= 122)) {
        if (IME.EnglishMode.checked) {
            if (IME.FullShape.checked) {
                SendStr(FullShape_SmallAZ[key - 97]);
                return (false);
            }
            return (true);
        } else {
            s = IME.Comp.value;
            if (s.length < MAX) {
                if (key >= 97 && key <= 122) {
                    IME.Comp.value += AsciiStr[key - 97];
                }
                else {
                    // 加了这个
                    IME.Comp.value += "'";
                    appendTrace(IME.Comp.value)
                }
                IME.Cand.value = "";
                var index = Grep(IME.Comp.value);

                if (index < 0) {
                    return false;
                }
            }
            return (false);
        }
    }

    // Gecko 的某些键会产生两个KeyCode，如?和/，须取消其中一个，否则将一键两字
    if (browser == 2) {
        switch (key) {
            case 47: case 63:
                if (!IME.EnglishMode.checked || IME.FullShape.checked) {
                    return (false);
                }
                break;
        }
    }

    return (true);
}

function ImeKeyUp(e) {
    var key = e.which ? e.which : e.keyCode;

    //==Ctrl
    if (key == 17 || key == 57402) {
        if (CtrlDown == true) {
            IME.EnglishMode.checked = !IME.EnglishMode.checked;
        }
    }

    return (true);
}

function BodyOnLoad() {
    browser =
    (navigator.appName.indexOf('Microsoft') != -1) ? 1 :
    (navigator.appName.indexOf('Netscape') != -1) ? 2 :
    (navigator.appName.indexOf('Opera') != -1) ? 3 :
    4;

    // Gecko 的JavaScript须以DOM方式表示物件，getElementById是“方便法”。IE亦通晓此法。Opera似乎亦晓得。
    IME = {
        InputArea: document.getElementById("InputArea"),
        Comp: document.getElementById("Comp"),
        Cand: document.getElementById("Cand"),

        EnglishMode: document.getElementById("EnglishMode"),
        FullShape: document.getElementById("FullShape"),
        AutoUp: document.getElementById("AutoUp"),
        arabicNumerals:true
    }
    
    

    //IME.InputArea.focus();
}

//BETA
function LoadImeTable() {
    //CodeList.clear;
    //document.write("<SCRIPT LANGUAGE='JavaScript1.2' SRC='" + news.js + ' TYPE='text/javascript'><\/SCRIPT>");
}

function appendTrace(text) {
    var traceElement = document.getElementById('TraceConsole');
    if (traceElement && (traceElement.tagName.toUpperCase() === 'TEXTAREA')) {
        traceElement.value += text + '\n';
    }
}